package java_thinking.unit_21.Exercise.barrier;

import java.util.concurrent.CountDownLatch;

/**
 * @Desc:   演示的场景是5位运动员参加跑步比赛，发令枪打响后，5个计时器开始分别计时，直到所有运动员都到达终点。
 *          1.计数器先启动，然后启动子线程
 *          2.一个主线程，等待 for 里面的多个子线程到达
 * @author: cww
 * @DateTime: 2019-07-14 10:29
 */

public class CountDownLatchDemo {
    public static void main(String[] args) {
        int athleteNum = 5;
        Timer timer = new Timer(athleteNum);
        //一个主线程，等待 for 里面的多个子线程到达
        new Thread(timer).start();
        new Thread(timer).start();
        for (int i = 0; i < athleteNum; i++) {
            new Thread(new Athlete(timer, "athlete" + i)).start();
        }
    }
}

class Timer implements Runnable {
    CountDownLatch countDownLatch;

    public Timer(int numOfAthlete) {
        this.countDownLatch = new CountDownLatch(numOfAthlete);
    }

    /**
     * 运动员到达后计数减一，并打印还有多少运动员还未到达
     * @param athleteName
     */
    public void recordResult(String athleteName, long startTime) {
        System.out.println(athleteName + " has arrived");
        System.out.println(athleteName + " used Time : " + ((System.nanoTime() / 1000) - startTime));
        countDownLatch.countDown();
        System.out.println("There are " + countDownLatch.getCount() + " athlete did not reach the end");
    }

    @Override
    public void run() {
        try {
            System.out.println("Start ...");
            countDownLatch.await();
            System.out.println("All the athlete have arrived");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Athlete implements Runnable {
    Timer timer;
    String athleteName;

    public Athlete(Timer timer, String athleteName) {
        this.athleteName = athleteName;
        this.timer = timer;
    }

    /**
     * 运动员开始奔跑
     */
    @Override
    public void run() {
        try {
            System.out.println(athleteName + " start running");
            long duration = (long) Math.random() * 10;
            long startTime = System.nanoTime() / 1000;

            Thread.sleep(1000 * 1000);
            timer.recordResult(athleteName, startTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}